package main

import (
	"encoding/json"
	"log"
	"net/http"
	"sync"
	"time"

	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
	_ "modernc.org/sqlite"
)

type Alert struct {
	Type        string  `json:"type"`
	Timestamp   float64 `json:"timestamp"`
	ImageBase64 string  `json:"image_base64"`
}

const (
	alarmIP   = "192.168.137.24"
	alarmPort = 6000
	alarmCmd  = "$01130601C8E3#"
	wsURL     = "ws://localhost:8080"
)

var (
	clients    = make(map[*websocket.Conn]bool)
	clientsMux sync.Mutex
	upgrader   = websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool { return true },
	}
)

func registerAlertRoutes(r *mux.Router) {
	r.HandleFunc("/api/alert", withCORS(alertHandler)).Methods("POST", "OPTIONS")
	r.HandleFunc("/api/alerts", withCORS(listAlertsHandler)).Methods("GET", "OPTIONS")
	r.HandleFunc("/ws", wsHandler) // WebSocket 不需要 CORS
}

func alertHandler(w http.ResponseWriter, r *http.Request) {
	var alert Alert
	err := json.NewDecoder(r.Body).Decode(&alert)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	_, err = DB.Exec("INSERT INTO alerts(type, timestamp, image_base64) VALUES (?, ?, ?)",
		alert.Type, alert.Timestamp, alert.ImageBase64)
	if err != nil {
		http.Error(w, "数据库插入失败", http.StatusInternalServerError)
		return
	}

	log.Printf("接收报警 类型:%s 时间:%f\n", alert.Type, alert.Timestamp)

	if isAlertType(alert.Type) {
		go broadcastMessage(alarmCmd)
		log.Println("触发报警指令广播给WebSocket客户端")

		go func() {
			err := sendWebSocketCommand(wsURL, alarmCmd)
			if err != nil {
				log.Printf("发送报警指令到设备失败: %v\n", err)
			} else {
				log.Println("成功发送报警指令到设备")
			}
		}()
	}
	w.Header().Set("Content-Type", "application/json")
	w.Write([]byte(`{"status":"ok"}`))
}

func isAlertType(alertType string) bool {
	switch alertType {
	case "falling", "fire", "fight", "gathering":
		return true
	}
	return false
}

func wsHandler(w http.ResponseWriter, r *http.Request) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println("升级WebSocket失败:", err)
		return
	}
	defer conn.Close()

	clientsMux.Lock()
	clients[conn] = true
	clientsMux.Unlock()

	log.Println("WebSocket客户端连接")

	for {
		_, msg, err := conn.ReadMessage()
		if err != nil {
			log.Println("WebSocket读消息失败:", err)
			break
		}
		log.Printf("收到客户端消息: %s\n", msg)

		err = conn.WriteMessage(websocket.TextMessage, []byte("收到消息: "+string(msg)))
		if err != nil {
			log.Println("WebSocket写消息失败:", err)
			break
		}
	}

	clientsMux.Lock()
	delete(clients, conn)
	clientsMux.Unlock()
	log.Println("WebSocket客户端断开")
}

func broadcastMessage(message string) {
	clientsMux.Lock()
	defer clientsMux.Unlock()

	for client := range clients {
		err := client.WriteMessage(websocket.TextMessage, []byte(message))
		if err != nil {
			log.Println("广播消息失败，移除客户端:", err)
			client.Close()
			delete(clients, client)
		}
	}
}

func listAlertsHandler(w http.ResponseWriter, r *http.Request) {
	rows, err := DB.Query("SELECT id, type, timestamp, image_base64 FROM alerts ORDER BY timestamp DESC")
	if err != nil {
		http.Error(w, "查询失败: "+err.Error(), http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	var alerts []Alert
	for rows.Next() {
		var alert Alert
		var id int
		err := rows.Scan(&id, &alert.Type, &alert.Timestamp, &alert.ImageBase64)
		if err != nil {
			log.Println("解析失败:", err)
			continue
		}
		alerts = append(alerts, alert)
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(alerts)
}

func sendWebSocketCommand(wsURL string, cmd string) error {
	// 连接 WebSocket
	log.Println("正在连接 WebSocket:", wsURL)
	conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
	if err != nil {
		return err
	}
	defer func() {
		log.Println("关闭 WebSocket 连接")
		conn.Close()
	}()

	log.Println("WebSocket 已连接")

	// 写入命令
	log.Printf("发送指令: %s\n", cmd)
	if err := conn.WriteMessage(websocket.TextMessage, []byte(cmd)); err != nil {
		return err
	}

	// 尝试读取返回消息
	conn.SetReadDeadline(time.Now().Add(3 * time.Second))
	msgType, msg, err := conn.ReadMessage()
	if err != nil {
		log.Println("无响应或读取失败（正常可能不返回）:", err)
	} else if msgType == websocket.TextMessage {
		log.Printf("收到桥接反馈: %s\n", string(msg))
	} else {
		log.Printf("收到非文本反馈（类型: %d)", msgType)
	}

	return nil
}
